#ifndef __FWAPPLICATION_H__
#define __FWAPPLICATION_H__

#include <string>
#include <functional>
#include <map>
#include "plat/nonecopyable.h"
#include "os/msgqueue.h"
#include "os/thread.h"
#include "os/timer.h"
#include "os/mutex.h"
#include "log/logger.h"
#include "applicationconfiguration.h"

#define FW_APPLICATION_THREAD_STACK_SIZE (128*4)
#define FW_APPLICATION_MQ_MAX_SIZE  256
#define FW_APPLICATION_TIMER_EVENT_MAX_SIZE  50
#define FW_APPLICATION_TIMER_INTERVAL 1

#define FW_APPLICATION_PREV_EVENT_MAX_SIZE 20

class ApplicationEvent;

using APPLICATION_EVENT_EXEC_FUNC = std::function<void(ApplicationEvent *ev)>;
using APPLICATION_CALLER_FUNC = std::function<void(void)>;

enum class ApplicationEventType
{
    //无效
    None = -1,
    // 主线程调用
    ThreadCall = 0,
    // 主定时器调用
    TimerCall
};

class ApplicationEvent : public NoneCopyable
{
public:
    ApplicationEventType Type = ApplicationEventType::None;
    void *Tag = nullptr;
    bool IsPreAllocated = false;
    
public:
    explicit ApplicationEvent(ApplicationEventType type, void *tag = nullptr)
    {
        Type = type;
        Tag = tag;
    }

    virtual ~ApplicationEvent(){}
};

class ThreadCallerEvent : public ApplicationEvent
{
public:
    APPLICATION_CALLER_FUNC Func = nullptr;

public:
    explicit ThreadCallerEvent():ApplicationEvent(ApplicationEventType::ThreadCall)
    {
        
    } 

    explicit ThreadCallerEvent(const APPLICATION_CALLER_FUNC &func)
        :ApplicationEvent(ApplicationEventType::ThreadCall)
    {
        Func = func;
    }

    virtual ~ThreadCallerEvent(){}
};

class TimerCallerEvent : public ApplicationEvent
{
public:
    APPLICATION_CALLER_FUNC Func = nullptr;
    Timer::TimerType Type = Timer::TimerType::Period;
    int Period = 0;
    //
    int Id = 0; //唯一ID
    int CurrentMs = 0; //当前定时器计时

public:
    explicit TimerCallerEvent(const APPLICATION_CALLER_FUNC &func, Timer::TimerType type, int period)
        :ApplicationEvent(ApplicationEventType::TimerCall)
    {
        Func = func;
        Type = type;
        Period = period;
    }

    virtual ~TimerCallerEvent(){}
};

/// @brief fw application
///        只能有一个application
/// @      application 有二个线程，1、loop线程 2、event 线程
class FwApplication : public NoneCopyable
{
private:
    explicit FwApplication();

public:
    virtual ~FwApplication();

public:
    static FwApplication &Instance();
    
public:
    inline AapplicationConfiguration &Configuration(){return m_appConfiguration;}

    void SendEvent(ApplicationEvent *event);

    //Application线程里执行
    //Post支持中断调用
    void Post(const APPLICATION_CALLER_FUNC &func);
    void Send(const APPLICATION_CALLER_FUNC &func);
    
    //Application定时器里执行
    int CallOnOneShot(const APPLICATION_CALLER_FUNC &func, int period);
    //注意，周期call，不能重复添加
    int CallPeriod(const APPLICATION_CALLER_FUNC &func, int period);

    void CallImmediately(int id);
    void RemoveCall(int id);
    bool ExistsCall(int id);

public:
    bool IsRunning();
    void Start();
    void Shutdown();

protected:
    virtual void OnStartUp();
    virtual void OnShutdown();
    virtual void OnLoop();
    virtual void OnEvent(ApplicationEvent *event);

private:
    void HandleTimer(int id = -1);
    int SendTimerCallEventImpl(const APPLICATION_CALLER_FUNC &func, Timer::TimerType type, int period);
    void HandleEvent(ApplicationEvent *event);
    void StartImpl();
    void TaskLoopImpl();

public:
    bool LoggerEnable = true;
    LoggerWriteMode LoggerMode = LoggerWriteMode::ASync;
    LoggerLevel LoggerLevel = LoggerLevel::Debug;

private:
    MsgQueue<ApplicationEvent*, FW_APPLICATION_MQ_MAX_SIZE> m_msgQueue;

    Thread m_thread{FW_APPLICATION_THREAD_STACK_SIZE};
    int m_currentTimerExecId = 0;
    std::map<int, TimerCallerEvent*> m_timerEventMap;
    Mutex m_timerEventLock;
    Mutex m_timerEventIdLock;
    Timer m_timer;

    //预分配
    int m_threadCallerIndex = -1;
    ThreadCallerEvent m_threadCallerEvents[FW_APPLICATION_PREV_EVENT_MAX_SIZE];

    AapplicationConfiguration m_appConfiguration;
};

#endif // __FWAPPLICATION_H__
